package com.huwaiwai001.map;

import java.util.AbstractMap;
import java.util.Map;
import java.util.Set;

/**
 * Created by hww on 2018/12/17 11:17 PM.
 */
public class MyHashMap<K, V> extends AbstractMap<K, V> {

    int initialCapacity = 1 << 1;

    Node<K, V> [] table;

    int size;

    public MyHashMap() {
        table = new Node[initialCapacity];
    }

    @Override
    public V get(Object key) {
        if (key == null) {
            return getValueForNull();
        }
        int h = hash(key.hashCode());
        Node<K, V> node = table[h];
        if (node == null) {
            return null;
        }
        while (node != null) {
            if (key.equals(node.key)) {
                return node.value;
            }
            node = node.next;
        }
        return null;
    }

    @Override
    public V put(K key, V value) {
        if (key == null) {
            return putValueForNull(key, value);
        }
        int h = hash(key.hashCode());
        Node<K, V> node = table[h];
        if (node == null) {
            table[h] = new Node<>(key, value, null);
            return null;
        }
        do {
            if (key.equals(node.key)) {
                V oldValue = node.value;
                node.value = value;
                return oldValue;
            }
        } while ((node = node.next) != null);

        Node<K, V> newNode = new Node<>(key, value, null);
        newNode.next = table[h];
        table[h] = newNode;
        return null;
    }

    private V putValueForNull(K key, V value) {
        Node<K, V> node = table[0];
        if (node == null) {
            table[0] = new Node<>(key, value, null);
            return null;
        }
        do {
            if (node.key == null) {
                V oldValue = node.value;
                node.value = value;
                return oldValue;
            }
        } while ((node = node.next) != null);

        Node<K, V> newNode = new Node<>(key, value, null);
        newNode.next = table[0];
        table[0] = newNode;
        return null;
    }

    private int hash(int hashCode) {
        return hashCode & (initialCapacity - 1);
    }

    private V getValueForNull() {
        Node<K, V> node = table[0];
        if (node == null) {
            return null;
        }
        while (node != null) {
            if (node.key == null) {
                return node.value;
            }
            node = node.next;
        }
        return null;
    }

    @Override
    public Set<Entry<K, V>> entrySet() {
        return null;
    }

    static class Node<K, V> implements Map.Entry<K, V> {

        final K key;
        V value;
        Node next;

        Node(K key, V value, Node next) {
            this.key = key;
            this.value = value;
            this.next = next;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }
    }

}
